iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 13
0

https://ithelp.ithome.com.tw/upload/images/20181028/20110801Be11dViHCG.png

我們在前面的章節介紹了 函式( Function ),他是可以執行特定任務的獨立區塊程式碼,而 Swift 更進階的提供了兩個型別的語法:類別 ( class ) 及 結構( struct ),這兩個型別語法可以讓我們將多個相關的值及函數儲存在內,以及更多的特性

我們會遇到一個問題:到底 struct 和 class 到底差在哪?以下我們對 struct 及 class 做一個比較:

struct 及 class 相同的地方:
・屬性 ( property ):用於儲存值
・方法 ( method ):用於提供功能
・下標 ( subscript):用於存取值
・建構器 ( initializer ):用於生成初始化值
・擴展 ( extension ):增加預設實作功能
・協定 ( protocol ):對某類別提供標準功能

class 還比 struct 多了以下功能:
・繼承 ( inherit ):class 可以繼承另一個 class 的內容
・解構器 ( deinitializer ):允許一個類別實體釋放其所被分配的資源
・型別轉換:允許在執行時檢查和轉換一個類別實體的型別
・參考計數:

語法:

定義一個 class 或 struck 要分別使用 class 或 struck 等關鍵字

class 類別名稱 {
類別內屬性、方法或其他可以定義在內的屬性
}
struck 結構名稱 {
結構內屬性、方法或其他可以定義在內的屬性
}

這裡有幾點注意一下:
・class 或 struct 內的常數或變數稱之為屬性 ( property )
・class 或 struct 內的 function,稱之為方法 ( method )
・每次定義 class 或 struct 時,實際上是定義了一個新的型別,所以習慣上會以 大駝峰式命名法 來為 class 或 struct 命名,以符合 Swift 型別的命名風格

https://ithelp.ithome.com.tw/upload/images/20181028/20110801zyWdTdYRHf.png

上述程式碼中,我們先行定義了一個角色設定的結構,這個結構裡面包含了兩個屬性:hp 及 mp,分別表示了角色的血量及魔力

接著我們定義了一個類別,來描述角色的基本屬性。而這個類別包含了三個屬性,第一個為角色狀態,會被初始化一個結構的實體;第二個為攻擊速度;最後一個為角色暱稱。

類別與結構實體

定義一個類別或結構,就像是給一個固定的規格,以遊戲來說明的話,就是這個角色一開始有的血量、魔力、攻擊速度以及角色暱稱。而我們在使用時,就必須按這這個規格 ( 也就是類別或結構 )來創建這個角色,這個動作就叫實例 ( instance )

類別與結構都使用建構器來實例化,建構器最簡單的形式就是在類別或結構後面名稱後面加上 ( ),這種實例化的方法,其內部的屬性都會初始化成預設值

https://ithelp.ithome.com.tw/upload/images/20181028/20110801dMEucrh6X8.png

取得屬性

使用點語法可以取得實例後的屬性,規則就是在實例名稱後面加上一個點,然後接著屬性名稱:
https://ithelp.ithome.com.tw/upload/images/20181028/2011080103lWODVSQZ.png

我們也可以取得子屬性,例如在 testGameCreate 中的 start 屬性:

https://ithelp.ithome.com.tw/upload/images/20181028/201108018OITGcmF7W.png

當然,我們也可以指派值給實例後屬性:

https://ithelp.ithome.com.tw/upload/images/20181028/20110801RD1aYBEAs6.png

結構型別成員逐一建構器

所有結構都有自動生成的成員逐一建構器,當要生成一個結構的實體時,用來初始化實體的屬性:

https://ithelp.ithome.com.tw/upload/images/20181028/20110801NcDt2JRsWJ.png

值型別及參考型別

Swift 以記憶體配置不同來說,分為值型別 ( value type )及參考型別( referce type )。值型別會實際儲存值;參考型別則會將值儲存在記憶體所配置的位置裡。

結構 ( struct ) 和列舉 ( enumeration )是值型別

值型別在被指派給一個變數、常數或在被傳遞給一個函式時,實際上的操作是拷貝。指派或是傳遞後,兩者值即各自獨立,不互相影響。

而在前面的語法中,已經大量的使用值型別。實際上,Swift 中的基本型別:整數、浮點數、字串、布林值、陣列及字典,都是值型別,而且背後都是以結構的形式實作。

結構和列舉也都是值型別,代表他們的實體及其內任何值型別的屬性,在指派或傳遞時被複製:

https://ithelp.ithome.com.tw/upload/images/20181028/20110801o9NwjL4wds.png

在 firstPlayer 被指派給 iAmFirstPlayer 時,其實是將 firstPlayer 內的值進行拷貝,接著將拷貝的資料儲存給新的實體 iAmFirstPlayer,兩者是完全獨立的實體,彼此不會互相影響。

類別是參考型別

參考型別( reference type )在被指派給一個變數、常數或被傳遞給一個函式時,操作的不是其拷貝,而是已存在的實體本身:

https://ithelp.ithome.com.tw/upload/images/20181028/20110801eOo0DpZk8w.png

在這裡要注意,雖然 secondPlayer 及 evolution 都被宣告為常數,卻都可以改變其內的屬性 ( secondPlayer.attackSpeed 及 evolution.attackSpeed ),因為這兩個常數儲存的是 GameCreate 類別實體的參考,而不是儲存這個實體,所以實體的 attackSpeed 這兩個實體可以被修改,但不會修改到常數的值。

恆等運算子

因為類別是參考型別,可能有多個常數和變數在後台同時參考某一個類別實體,所以 Swift 提供了兩個恆等運算子,能夠判斷兩個變數或常數是不是參考同一個類別實體:

https://ithelp.ithome.com.tw/upload/images/20181028/20110801lL2CrBNhCh.png

class 和 struct 的抉擇

class 和 struct 有許多相似的地方,他們都可以定義自定義數據類型,作為程式碼的建構區塊。總之,class 是用來傳遞的;而 struct 則是透過複製來傳遞,這說明了他們適用於不同任務,所以當我們考慮項目所需數據結構及功能時,就要確定每個數據結構定義是 class 還是 struct。

按照準則,當符合以下一項或是多項情況時可以考慮創建 struct:

Struct 的主要目的封裝一些相對簡單的數據值。
當賦值或傳遞 Struct 實例時,合理的期望封裝的值是被複製的,而不是引用的。
Struct 儲存的任何屬性都是他們自己的值類型,它們也將被複製而不是引用。
該 Struct 不需要繼承其他現有類型的屬性或行為。
適合使用 Struct 創建的例子如下:

幾何形狀的大小,可能封裝了一個 width 和 height 屬性,兩者類型都為 Double
一定範圍的路徑,可能封裝了一個 start 和 length 屬性,兩者類型都為 Int
三維坐標系的一個點,可能封裝了 x , y 和 z 三個屬性,類型都為 Double
在其他情況下,你應該定義一個 Class 並創建該 Class 的實例,透過引用來管理和傳遞。實際上,這也代表著大多數自定義的數據結構應該為 Class 而不是 Struct。

今天的 class 及 struct 就到這裡囉!如果有其他的問題歡迎留言或是寄信給我!(*´∀`)


上一篇
Swift4.2 Day-12 Enumeration
下一篇
Swift 4.2 Day-14 Properties
系列文
菜比八iOS程式開發30天自我挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言